﻿namespace FsCheck.Test

module Random =  

    open System
    open Xunit
    open FsCheck
    open FsCheck.Xunit
    open Swensen.Unquote

    
    [<Fact>]
    let ``mkStdGen should not hang when seed is min or max value``() =
        Random.CreateWithSeed UInt64.MinValue |> ignore
        Random.CreateWithSeed UInt64.MaxValue |> ignore
        
    // these tests may be helpful to check Random progress guarantees. See #356
    [<Property(Replay = "10538531436017130025,14826463994991344553", MaxTest = 30000, EndSize = 30000)>]
    let ``Random should not hang on 30k ints`` () =
        true

    [<Fact>]
    let ``Random should not hang on bad case`` () = 
        let rnd = Random.CreateWithSeedAndGamma (13471455474525100574UL,7555858534656909083UL)
        let n = 19938
        Random.RangeInt (0, n, rnd)

    // the 100 first nextlong() generated by jdk8's SplittableRandom with seed 25122001
    let jdk8int64 = [| 8392291492603386512L; 380721947090852919L; 8187156289887658572L; 758676128606796808L; 7537011226607776231L; 7382942362971095141L; -2734066992429644822L; 7392502300013873057L; -4379021889898248705L; 920908937198061449L; 838985796884301729L; -7882053883716044909L; 4181059044861220374L; -1900048976813918321L; 7219101215850546790L; 778752108544929874L; 4868227715648373197L; -8859388532018080905L; -4220469000076161871L; -4253445752809149355L; -7626411335122526042L; -3239027163223609746L; 9113657224088328148L; 4815983952368409704L; -3586727581691170451L; 3228467171483802169L; -3388271240371943314L; -4190450661897471596L; -7500460061335833135L; -5252103618679142907L; -2645329218837224457L; -3219039224417961788L; -8631066818897614733L; -6685083028759243684L; 5152607045987713973L; 6197286841806084036L; 7373957600441511006L; 2440923560599908350L; 2256736229294343876L; -3976992258665280500L; 2705944819422153038L; 611584505403713975L; 4391435429367768775L; -2451038390962499727L; 1959883562230657464L; 4311086592775368885L; 3473485381214274910L; -286817309522846800L; -8393018113866694425L; -6572640908002801961L; 3520476012025570491L; -8891302870266944016L; 1448331745345157857L; -6268033314303019079L; 193207596813387131L; 1837750191471710133L; 897094913700459534L; 7139805427398545697L; -5918212670555908734L; -3233150548323652350L; 8464510983171334111L; 8547683696310093789L; 6502342234246383569L; 6305934180084236069L; -7879002140392221937L; 4782209224570070123L; -6390929690190989013L; -885737066266153421L; 7422343067477294501L; 6711930832071026040L; -4044041802094370747L; 4921281455888376583L; 4477129825441738380L; 3727851531659398457L; 6393564445210805522L; 1954010057143906087L; -8358725625740792753L; 4528829488236322014L; -1017377668787949565L; 8441082179647158889L; -1489123834457278184L; 3693550890885843709L; -2545231537440809668L; 427828882533968946L; -3978458043524133744L; -1322179194729615499L; 2842268999418638175L; 6039909617528529145L; -189267091331895394L; 2184874974988318835L; 3253867630456867005L; -3307824831398277809L; 4564759067830756535L; -6831261440311025234L; -1814662364111708283L; 1468302212572746857L; 5388031130596899450L; -4202121979082117842L; -1120564773273990716L; 6928751360854833768L |]

    [<Fact>]
    let ``returns same sequence of int64 as JDK8``() =
        let r = ref (Random.CreateWithSeed 25122001UL)
        let longs = [| for i in 1..100 -> Random.NextInt64 r |]
        test <@ Array.zip jdk8int64 longs |> Array.forall(fun (l,r) -> l = r) @>

    // the 100 first nextfloat() generated by jdk8's SplittableRandom with seed 25122001
    let jdk8float64 = [| 0.4549470334206104; 0.020638978107440642; 0.44382663179872806; 0.041127915342419; 0.40858219729678935; 0.40023010746342624; 0.8517859313543434; 0.40074835268895637; 0.7626127476805369; 0.049922573518572655; 0.045481511183322; 0.5727130027813627; 0.22665566498643508; 0.8969981385754744; 0.3913482610808954; 0.04221623639560401; 0.2639071532730055; 0.5197315853346416; 0.771207917060485; 0.7694202437127539; 0.586571413109604; 0.82441198564467; 0.49405234808223875; 0.26107501319065773; 0.8055631081908377; 0.17501555605604346; 0.8163214480109292; 0.772835214433872; 0.5933992453429464; 0.7152828923254546; 0.8565964156998649; 0.8254955339784996; 0.5321089302041827; 0.6376009228486625; 0.2793233876611998; 0.33595559287009924; 0.3997430425107341; 0.13232273136367356; 0.12233791612638356; 0.7844068176598534; 0.1466895625921697; 0.03315406247085895; 0.23806019164251735; 0.867128942583654; 0.10624550079945538; 0.2337044724830093; 0.1882980198204578; 0.9844516024954441; 0.5450135763617769; 0.6436964224288131; 0.19084538702106135; 0.5180015055914988; 0.07851422123914709; 0.6602092331710574; 0.010473804810288811; 0.09962463750396389; 0.04863161271798666; 0.3870496277754649; 0.6791730482676022; 0.8247305575767397; 0.45886205984908857; 0.4633708616629164; 0.3524926788307088; 0.34184537687989625; 0.5728784381184406; 0.2592440815279544; 0.6535470072846409; 0.9519840974251649; 0.4023660239345802; 0.3638544994851922; 0.7807720546273544; 0.26678320229434016; 0.2427056941621789; 0.20208723646642668; 0.34659582307118164; 0.10592709745069728; 0.5468725758680787; 0.2455083384981117; 0.9448478460630934; 0.4575919818651063; 0.9192744351790737; 0.20022779500421006; 0.8620227218814026; 0.023192650194768683; 0.7843273573034352; 0.9283245222329507; 0.15407971119789432; 0.32742415644702616; 0.9897398104198972; 0.11844230972457737; 0.17639251769607978; 0.8206824565798244; 0.24745608491075055; 0.6296765752799165; 0.9016269561251201; 0.07959682243683219; 0.2920857528606343; 0.772202511061504; 0.9392540619202806; 0.37560836390253527 |]

    [<Fact>]
    let ``returns same sequence of float64 as JDK8``() =
        let r = ref (Random.CreateWithSeed 25122001UL)
        let floats = [| for i in 1..100 -> Random.NextDouble r |]
        test <@ Array.zip jdk8float64 floats |> Array.forall(fun (l,r) -> float l = r) @>

    // the 100 first nextlong() generated by jdk8's SplittableRandom with seed 25122001, splitting it first each time then calling nextLong
    let jdk8splits = [| -6183977328171972878L; 4007833804158996346L; -2895259710302547186L; 6242061246681775534L; 4693057156352709852L; 6862677099549126427L; 3038984301344487040L; -1200055194208506267L; -6170319730378511474L; -5531708796038855616L; 1331057534468982957L; 7249146091181991535L; 5128556169130775977L; 7575597996417727591L; 6936112374741147025L; 2804131022108550304L; 6178369856090177007L; 8485161414445536515L; 5620823932955157725L; -5678314742316773700L; -4570930250152718596L; -631662287275036281L; 4364031805758623393L; -272698244146580352L; -6046350887383827507L; 7942515459214416810L; -5750516709103528578L; 2171290454533396251L; 8739999972473709059L; 7926750701990108219L; 601171254121289918L; 3373699784849196225L; 5409122478956606724L; 5012597278880889967L; -3208966840265346647L; 7344376532297810397L; -4352618693893499902L; 8315114883912447022L; 7266602768619472995L; -9150029459462598135L; -379605575130771336L; 1253144842151547188L; 3178208818014238869L; -9020678188403772263L; 6914708912505443288L; -9018546557090338024L; 6104716526775889362L; -2751787922008557187L; 1260282004661545754L; 7845585421227842362L; 2509546711595461325L; -3879083117516693643L; 8007829388188235034L; -7706396012751570796L; 5881296307981542364L; -8146417138850385570L; 7921747644485360448L; 2407083934371167178L; 8429560725821132616L; -1598362250806254839L; -2558991249231402L; 4285124028839080879L; -2067065289303956208L; 801071044217542684L; 4039792650051152833L; -2175458631898164438L; 7161262514480946658L; 7100150565265263987L; 8541884673697013089L; -7207819280646094217L; 6226033766623896371L; -5167032647435300869L; -3107215772020158812L; 4514952926431664891L; 8343517972284606639L; 500715956815080928L; 4418485926618586950L; 5195718824161513303L; 881726772209204222L; 8965924269007607740L; -8444319269938479047L; -8267441886640689636L; -1859087615100435080L; -3388212677608366662L; -8476431298952260086L; 7309709646902553459L; 8915967827466411930L; -7431876701849627149L; 5551848090879967353L; -7105937139202432854L; -7147348563218948072L; 2195516818036844543L; -201605378395486049L; -4539098181289462501L; 1533876256908451755L; -6985925005254184204L; -2932777785686800817L; 3776054607777157824L; -945837442312781475L; -7796594121376621139L |] 

    [<Fact>]
    let ``returns same splits of int64 as JDK8``() =
        let r = ref (Random.CreateWithSeed 25122001UL)
        let l = ref (Random.CreateWithSeed 25122001UL)
        let longs = [| for i in 1..100 do Random.Split(!r,l,r); yield Random.NextInt64 r |]
        test <@ Array.zip jdk8splits longs |> Array.forall(fun (l,r) -> l = r) @>